// package: rewords-server-2024
// filename: dingCtrl
// author: diogoxiang@gmail.com
// time: 2024/11/20 10:23

package dingCtrl

import (
	"context"

	"github.com/gogf/gf/v2/errors/gerror"
	"github.com/gogf/gf/v2/util/gconv"

	"rewords-server-2024/api/ding"
	"rewords-server-2024/internal/consts"
	"rewords-server-2024/internal/dao/cmgox"
	"rewords-server-2024/internal/library/ahttp"
	"rewords-server-2024/internal/library/apptoken"
	"rewords-server-2024/internal/library/cfg"
	"rewords-server-2024/internal/library/ecode"
	"rewords-server-2024/internal/model/entity"
	"rewords-server-2024/internal/service"
)

var (
	Ding = new(cDing)
	// DingHost 钉钉 开放平台 接口地址
	DingHost = "https://api.dingtalk.com"
)

type cDing struct{}

func (c *cDing) GetAccessToken(ctx context.Context, req *ding.DingAccessTokenReq) (res *ding.DingAccessTokenRes, err error) {
	sling := ahttp.New()

	succeccRes := new(entity.DingTokenResp)
	errorRes := new(entity.DingResErr)
	// 创建请求
	resp, err := sling.New().Post(DingHost).Path("/v1.0/oauth2/userAccessToken").BodyJSON(map[string]string{
		"clientId":     cfg.GConfig.Ding.ClientId,
		"clientSecret": cfg.GConfig.Ding.ClientSecret,
		"code":         req.Code,
		"grantType":    "authorization_code",
	}).Receive(succeccRes, errorRes)

	if err != nil {
		return nil, err
	}

	if resp.StatusCode != 200 {
		//g.Log().Printf("Error response: %v", errorRes)
		return nil, gerror.NewCode(ecode.InvalidParams, errorRes.Message)
	}

	userInfo, err := getUserInfo(succeccRes.AccessToken)

	if err != nil {
		return nil, gerror.NewCode(ecode.InvalidParams, err.Error())
	}

	qBuilder := cmgox.NewConditionBuilder().
		AddOptionalCondition("unionid", "$eq", userInfo.UnionId).
		AddOptionalCondition("openid", "$eq", userInfo.OpenId).
		Build()

	result, err := service.Mgx().FindOne(ctx,
		consts.CsysUser,
		qBuilder,
		nil,
	)
	if err != nil {
		return nil, gerror.NewCode(ecode.InvalidParams, err.Error())
	}

	if result == nil {
		return nil, gerror.NewCode(ecode.DataNotFound)
	}
	var adminUser *entity.SysAdminUser

	if err := gconv.Struct(result, &adminUser); err != nil {
		return nil, gerror.NewCode(ecode.InvalidParams, err.Error())
	}

	token, _, err := apptoken.GenerateAdminToken(ctx, adminUser)

	if err != nil {
		return nil, gerror.NewCode(ecode.InvalidParams, err.Error())
	}

	return &ding.DingAccessTokenRes{
		Token:    token,
		UserInfo: adminUser,
	}, nil

}

func getUserInfo(accessToken string) (*entity.DingUserResp, error) {
	sling := ahttp.New()
	succeccRes := new(entity.DingUserResp)
	errorRes := new(entity.DingResErr)

	resp, err := sling.New().Add("x-acs-dingtalk-access-token", accessToken).Get(DingHost).Path("/v1.0/contact/users/me").Receive(succeccRes, errorRes)

	if err != nil {
		return nil, err
	}

	if resp.StatusCode != 200 {

		return nil, err
	}

	return succeccRes, nil
}
